package com.lagou.edu.message.server;

import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketConfig;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
import com.corundumstudio.socketio.namespace.Namespace;
import com.corundumstudio.socketio.protocol.Packet;
import com.corundumstudio.socketio.protocol.PacketType;
import com.lagou.edu.common.string.GsonUtil;
import com.lagou.edu.message.api.dto.Message;
import com.lagou.edu.message.util.ServerConfigUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
public class PushServer {

    public static final PushServer pushServer = new PushServer();
    private Namespace pushNamespace;
    private SocketIOServer server;
    private static List<SocketIOClient> clients = new ArrayList<SocketIOClient>();//用于保存所有客户端

    private PushServer() {
        final Configuration configuration = new Configuration();
        configuration.setOrigin(ServerConfigUtils.instance.getWebSocketOrigin());
        configuration.setPort(ServerConfigUtils.instance.getWebSocketPort());
        configuration.setContext(ServerConfigUtils.instance.getWebSocketContext());
//        configuration.setAuthorizationListener();  // redisson
//        configuration.setStoreFactory();  // auth
        // 可重用地址,防止处于TIME_WAIT的socket影响服务启动
        final SocketConfig socketConfig = new SocketConfig();
        socketConfig.setReuseAddress(true);
        configuration.setSocketConfig(socketConfig);
        
        server = new SocketIOServer(configuration);
        pushNamespace = (Namespace)server.addNamespace(ServerConfigUtils.instance.getWebSocketContext());
        
        // 添加一个连接监听器
        pushNamespace.addConnectListener(new ConnectListener() {
            @Override
            public void onConnect(final SocketIOClient socketIOClient) {
                clients.add(socketIOClient);
            }
        });
    
        //添加断开连接的监听器
        pushNamespace.addDisconnectListener(new DisconnectListener() {
            @Override
            public void onDisconnect(SocketIOClient client) {
                clients.remove(client);
            }
        });
    
    }

    /**
     * 推送消息
     *
     * @param message
     */
    public void push(Message message) {
        final String type = message.getType();
        final Integer userId = message.getUserId();
        final String json = GsonUtil.toJson(message);
    
        System.out.println("开始推送了..................");
        Packet packet = new Packet(PacketType.MESSAGE);
        packet.setSubType(PacketType.EVENT);
        packet.setName("message");
        ArrayList<Object> data = new ArrayList<>();
        data.add(json);
        packet.setData(data);
        packet.setNsp(pushNamespace.getName());
    
        for(SocketIOClient client : clients) {
            client.send(packet);
        }
    }

    /**
     * 同步启动服务；
     */
    public void start() {
        try {
            server.start();
        } catch (Exception e) {
            log.error("Push server start failed!", e);
            System.exit(-1);
        }
    }

    /**
     * 停止服务
     */
    public void stop() {
        server.stop();
    }

    public Map<String, Object> getStatus() {
        HashMap<String, Object> status = new HashMap<>();
        status.put("namespace", pushNamespace.getName());   // namespace
        status.put("rooms", pushNamespace.getRooms());
        status.put("clients", pushNamespace.getAllClients().size());
        return status;
    }

}
